package Env;
import java.util.Vector;



public class Environment {

	private final Graph graph;
	private Vector<Car>[] vertexes;
	private static boolean singleton=false;

	public Environment (Graph g) throws Exception{
		if (singleton)
			throw new Exception ("singleton already created");
		graph=g;
		vertexes=new Vector[graph.n+1];
		for (int i=0;i<=g.n;i++)
			vertexes[i]=new Vector<Car>();
		singleton=true;
	}

	public void addCar(int v, int speed, float f) throws Exception {
		vertexes[v].add(new Car(speed, f));
	}

	public float drive(int from,int to,Car car) throws Exception{
		//		System.out.println(car);
		vertexes[from].remove(car);
		vertexes[to].add(car);
		if (graph.isEdgeFlooded(from, to))
			return (graph.getEdgeCost(from, to)/(car.getSpeed()*car.getEff()));
		else
			return (graph.getEdgeCost(from, to)/(car.getSpeed()));

	}

	@Override
	public String toString() {
		String result = "Enviorment graph=\n" + graph + "\n\n\ncars=\n";
		int j;
		for (j=1; j<=graph.n; j++){
			if (vertexes[j].size()>0)
				result += "cars in vertex " + j + ":\n";
			for (Car c : vertexes[j]){
				result += c + "\n";
			}
		}
		return result;
	}

	public Graph getGraph(){
		return graph;
	}

	public Vector<Car> getCars(int vertex) {
		return vertexes[vertex];
	}

	public Car maxCar(int v) {
		Car ans=null;
		int speed=0;
		for(Car i:vertexes[v]){
			if (i.getSpeed()>speed){
				ans=i;
				speed=i.getSpeed();
			}
		}
		return ans;
	}

	public Car maxEffCar(int v) {
		Car ans=null;
		float speed=0;
		for(Car i:vertexes[v]){
			if (i.getEff()>0 && i.getSpeed()*i.getEff()>speed){
				ans=i;
				speed=i.getSpeed()*i.getEff();
			}
		}
		return ans;
	}

	public boolean checkForEffCar(int v) {
		for(Car i:vertexes[v]){
			if (i.getEff()>0) return true;
		}
		return false;
	}

	public int maxEdge(Graph g, Vector<Integer> connected,int pos,int last) throws Exception {
		float max=-1;
		int maxV=-1;
		for (Integer i:connected){
			if (last==i)
				continue;
			if (g.getEdgeCost(pos, i)>max){
				max=g.getEdgeCost(pos, i);
				maxV=i;
			}
		}
		return maxV;
	}

	public int maxNonFloodedEdge(Graph g, Vector<Integer> connected,int pos,Integer last) throws Exception {
		float max=-1;
		int maxV=-1;

		for (Integer i:connected){
			if (last!=null&& last==i||g.isEdgeFlooded(pos, i))
				continue;
			if (g.getEdgeCost(pos, i)>max){
				max=g.getEdgeCost(pos, i);
				maxV=i;
			}
		}
		return maxV;
	}

	public State getState(int position) {
		return new State(position,vertexes);
	}
	
	public Vector<State> expandState(State s) throws Exception{
		int pos=s.getPosition();
		Vector<Integer> connected= graph.getAllConnected(pos);
		Vector<Car> cars= s.getVertexes()[s.getPosition()];
		Vector<State> ans=new Vector<State>();
		for (Car i:cars){
			boolean eff= i.getEff()>0;
			for (Integer j:connected){
				if (eff)
					ans.add(new State(s,j,i));
				else if (!graph.isEdgeFlooded(pos, j))
					ans.add(new State(s,j,i));
			}
		}
		
		
		
		return ans;
	}








}
